package src.model.gameWorld;


/**
 * <b>Overview</b><br>
 * The position class encapsulates the idea of a position in the world.
 * It is identified by a simple x,y value.  calling the isValid() method
 * will return true if it is within the boundaries as specfied.
 * <br><br>
 * <b>Responsibilities</b><br>
 * Positions are only responsible for holding position information
 * <br><br>
 * <b>Collaborators</b><br>
 * None.
 * <br><br>
 * <b>Implementor</b> - Brent <br>
 * <b>Testor</b> - Bruce <br>
 *
 * @author Brent
 *
 */
public class Position
{
	private int x, y;
	private static int maxX, maxY;

	/**
	 * Create a new Position with the given coordinates
	 * @param x - x coordinate (column)
	 * @param y - y coordinate (column)
	 */
	public Position(int x, int y)
	{
		this.x = x;
		this.y = y;
	}

	/**
	 * Accessor for the X coordinate
	 * @return integer representation of x
	 */
	public int X()
	{
		return x;
	}

	/**
	 * Accessor for the Y coordinate
	 * @return integer representation of y
	 */
	public int Y()
	{
		return y;
	}

	/**
	 * Setter for the X coordinate
	 * @param x - the new X coordinate
	 */
	public void setX(int x)
	{
		this.x = x;
	}

	/**
	 * Setter for the Y coordinate
	 * @param y - the new Y coordinate
	 */
	public void setY(int y)
	{
		this.y = y;
	}

	/**
	 * Adds a value to the X coordinate and returns true if and only if
	 * the resulting position is valid.
	 * @param x - the value to be added to the coordinate
	 * @return - true if the modification is valid.
	 */
	public boolean incX(int x){
		if(isValid(this.x + x, this.y)){
			this.x += x;
			return true;
		}
		return false;
	}

	/**
	 * Adds a value to the Y coordinate and returns true if and only if
	 * the resulting position is valid.
	 * @param y - the value to be added to the coordinate
	 * @return - true if the modification is valid.
	 */
	public boolean incY(int y){
		if(isValid(this.x, this.y + y)){
			this.y += y;
			return true;
		}
		return false;
	}

	/**
	 * True if the position is valid (lies witin the boundaries)
	 * @return - True if and only if the position is valid.
	 */
	public boolean isValid()
	{
		return isValid(this.X(), this.Y());
	}

	/**
	 * True if the position specified by x and y is valid
	 * @param x - an x coordinate
	 * @param y - an y coordinate
	 * @return - true if the position (x, y) is true
	 */
	private boolean isValid(int x, int y){
		return (x >= 0 && x < maxX) && (y >= 0 && y < maxY);
	}


	/* (non-Javadoc)
	 * @see java.lang.Object#equals(java.lang.Object)
	 */
	public boolean equals(Object o)
	{
		return o instanceof Position ? equals((Position)o) : false;
	}

	public boolean equals(Position o)
	{
		return o == null ? false : o.X() == X() && o.Y() == Y();
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#hashCode()
	 */
	public int hashCode()
	{
		int hashY = y << 15;

		return x + hashY;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	public String toString()
	{
		return "(" + x + ", " + y + ")";
	}

	/**
	 * Set the static X boundary
	 * @param x - the new X boundary
	 */
	public static void setXBoundary(int x)
	{
		maxX = x;
	}

	/**
	 * Set the static Y boundary
	 * @param y - the new Y boundary
	 */
	public static void setYBoundary(int y)
	{
		maxY = y;
	}

	/**
	 * Get the current X boundary
	 * @return the current X boundary
	 */
	public static int getXBoundary()
	{
		return maxX;
	}

	/**
	 * Get the current Y boundary
	 * @return the current Y boundary
	 */
	public static int getYBoundary()
	{
		return maxY;
	}
}